package com.wl.config;

import com.wl.filter.JwtLoginFilter;
import com.wl.filter.JwtVerifyFilter;
import com.wl.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private RsaKeyProperties prop;

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //指定认证对象的来源
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    //SpringSecurity配置信息(下面注释附SpringSecurity匹配规则)
    public void configure(HttpSecurity http) throws Exception {
        http.csrf()
            .disable()
            .exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint())
            .and()
            .authorizeRequests()
            //.antMatchers("/product").hasAnyRole("USER")
            .antMatchers("/product/findAll").hasAnyAuthority("ROLE_ALL_PRODUCT")
            .antMatchers("/product/addproduct").hasAnyAuthority("ROLE_ADD_PRODUCT")
            .anyRequest()
            .authenticated()
            .and()
            .addFilter(new JwtLoginFilter(super.authenticationManager(), prop))
            .addFilter(new JwtVerifyFilter(super.authenticationManager(), prop))
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    /**
     * 一 URL匹配
     * requestMatchers() 配置一个request Mather数组，参数为RequestMatcher 对象，其match 规则自定义,需要的时候放在最前面，对需要匹配的的规则进行自定义与过滤
     * authorizeRequests() URL权限配置
     * antMatchers() 配置一个request Mather 的 string数组，参数为 ant 路径格式， 直接匹配url
     * anyRequest 匹配任意url，无参 ,最好放在最后面
     *二 保护URL
     * authenticated() 保护UrL，需要用户登录
     * permitAll() 指定URL无需保护，一般应用与静态资源文件
     * hasRole(String role) 限制单个角色访问，角色将被增加 “ROLE_” .所以”ADMIN” 将和 “ROLE_ADMIN”进行比较. 另一个方法是hasAuthority(String authority)
     * hasAnyRole(String… roles) 允许多个角色访问. 另一个方法是hasAnyAuthority(String… authorities)
     * access(String attribute) 该方法使用 SPEL, 所以可以创建复杂的限制 例如如access("permitAll"), access("hasRole('ADMIN') and hasIpAddress('123.123.123.123')")
     * hasIpAddress(String ipaddressExpression) 限制IP地址或子网
     *三 登录login
     * formLogin() 基于表单登录
     * loginPage() 登录页
     * defaultSuccessUrl 登录成功后的默认处理页
     * failuerHandler登录失败之后的处理器
     * successHandler登录成功之后的处理器
     * failuerUrl登录失败之后系统转向的url，默认是this.loginPage + "?error"
     *四 登出logout
     * logoutUrl 登出url ， 默认是/logout， 它可以是一个ant path url
     * logoutSuccessUrl 登出成功后跳转的 url 默认是"/login?logout"
     * logoutSuccessHandler 登出成功处理器，设置后会把logoutSuccessUrl 置为null
     */
}
